﻿using System.Linq.Expressions;
using LinqKit;
using Shop.Model.Category;
using Shop.Model.DB;
using Shop.Model.FrontCategory;
using Shop.Model.Goods;
using Shop.RemoteModel;
using Shop.RemoteModel.Activity.Model;
using Shop.RemoteModel.Advert.Model;
using Shop.RemoteModel.AdvertPlace.Model;
using Shop.RemoteModel.Coupon.Model;
using Shop.RemoteModel.GoodsSku.Model;
using Shop.RemoteModel.LogisticsConfig.Model;
using Shop.RemoteModel.LogisticsTemplate.Model;
using Shop.RemoteModel.PageTemplate.Model;
using Shop.RemoteModel.SpuGoods.Model;
using SqlSugar;
using WeDonekRpc.Helper;
using WeDonekRpc.Helper.Validate;
using WeDonekRpc.SqlSugar.LinqKit;
namespace Shop.Repository.LinqHelper
{
    internal static class WhereLinq
    {
        public static Expression<Func<DBGoods, bool>> ToWhere ( this TopGetArg query )
        {
            ExpressionStarter<DBGoods> where = PredicateBuilder.New<DBGoods>();
            if ( query.CategoryId.HasValue && query.Lvl.HasValue )
            {
                switch ( query.Lvl.Value )
                {
                    case 1:
                        where = where.And(a => a.MainCategoryId == query.CategoryId.Value);
                        break;
                    case 2:
                        where = where.And(a => a.TwoCategoryId == query.CategoryId.Value);
                        break;
                    case 3:
                        where = where.And(a => a.ThreeCategoryId == query.CategoryId.Value);
                        break;
                    default:
                        where = where.And(a => a.CategoryId == query.CategoryId.Value);
                        break;
                }
            }
            if ( where.IsStarted )
            {
                return where;
            }
            return null;
        }

        public static Expression<Func<DBAdvertPlace, bool>> ToWhere ( this AdvertPlaceQueryParam param )
        {
            ExpressionStarter<DBAdvertPlace> where = PredicateBuilder.New<DBAdvertPlace>();
            if ( param.UseRange.HasValue )
            {
                where = where.And(a => a.UseRange == param.UseRange.Value);
            }
            if ( param.PlaceType.IsNotNull() )
            {
                where = where.And(a => a.PlaceType == param.PlaceType);
            }
            if ( param.PlaceStatus.HasValue )
            {
                where = where.And(a => a.PlaceStatus == param.PlaceStatus.Value);
            }
            if ( param.QueryKey.IsNotNull() )
            {
                where = where.And(a => a.PlaceTitle.Contains(param.QueryKey));
            }
            if ( where.IsStarted )
            {
                return where;
            }
            return null;
        }
        public static Expression<Func<DBAdvertPlace, bool>> ToWhere ( this AdvertPlaceGetParam param )
        {
            ExpressionStarter<DBAdvertPlace> where = PredicateBuilder.New<DBAdvertPlace>(a => a.PlaceType == param.PlaceType && a.UseRange == param.UseRange);
            if ( param.PlaceStatus.HasValue )
            {
                where = where.And(a => a.PlaceStatus == param.PlaceStatus.Value);
            }
            return where;
        }
        public static Expression<Func<DBPageTemplate, bool>> ToWhere ( this PageTemplateQuery query )
        {
            ExpressionStarter<DBPageTemplate> where = PredicateBuilder.New<DBPageTemplate>(a => a.TemplatePlace == query.Place && a.UseRange == query.UseRange);
            if ( query.Status.HasValue )
            {
                where = where.And(a => a.Status == query.Status.Value);
            }
            if ( !query.QueryKey.IsNull() )
            {
                where = where.And(a => a.TemplateName.Contains(query.QueryKey));
            }
            return where;
        }
        public static Expression<Func<DBGoodsSku, DBGoods, bool>> ToWhere ( this SkuQueryParam query )
        {
            ExpressionStarter<DBGoodsSku, DBGoods> where = LinqKitExtend.New<DBGoodsSku, DBGoods>(( a, b ) => b.Id == a.GoodsId);
            if ( !query.QueryKey.IsNull() )
            {
                where = query.QueryKey.Validate(ValidateFormat.数字字母)
                    ? (ExpressionStarter<DBGoodsSku, DBGoods>)where.And(( a, b ) => a.GoodsSku.StartsWith(query.QueryKey))
                    : (ExpressionStarter<DBGoodsSku, DBGoods>)where.And(( a, b ) => a.SkuName.Contains(query.QueryKey));
            }
            if ( query.CategoryId.HasValue && query.Lvl.HasValue )
            {
                switch ( query.Lvl.Value )
                {
                    case 1:
                        where = where.And(( a, b ) => b.MainCategoryId == query.CategoryId.Value);
                        break;
                    case 2:
                        where = where.And(( a, b ) => b.TwoCategoryId == query.CategoryId.Value);
                        break;
                    case 3:
                        where = where.And(( a, b ) => b.ThreeCategoryId == query.CategoryId.Value);
                        break;
                    default:
                        where = where.And(( a, b ) => b.CategoryId == query.CategoryId.Value);
                        break;
                }
            }
            return where.And(( a, b ) => b.Status == GoodsStatus.已发布 && SqlFunc.Subqueryable<DBGoodsSkuState>().Where(c => c.GoodsId == a.GoodsId && c.SpecsKey == a.SpecsKey && c.IsEnable == false).NotAny());
        }

        public static Expression<Func<DBShopCoupon, bool>> ToWhere ( this CouponQueryParam query )
        {
            ExpressionStarter<DBShopCoupon> where = PredicateBuilder.New<DBShopCoupon>();
            if ( query.CouponType.HasValue )
            {
                where = where.And(c => c.CouponType == query.CouponType.Value);
            }
            if ( query.UserRange.HasValue )
            {
                where = where.And(c => c.UserRange == query.UserRange.Value);
            }
            if ( query.PutInRange.HasValue )
            {
                where = where.And(c => c.PutInRange == query.PutInRange.Value);
            }
            if ( !query.Status.IsNull() )
            {
                where = where.And(c => query.Status.Contains(c.Status));
            }
            if ( query.Begin.HasValue && query.End.HasValue )
            {
                where = where.And(a => a.PutInBegin <= query.End.Value && a.PutInEnd >= query.Begin.Value);
            }
            else if ( query.Begin.HasValue )
            {
                where = where.And(a => a.PutInBegin >= query.Begin.Value);
            }
            else if ( query.End.HasValue )
            {
                where = where.And(a => a.PutInEnd <= query.End.Value);
            }
            if ( query.SkuId.HasValue )
            {
                where = where.And(c => SqlFunc.Subqueryable<DBShopCouponGoods>().Where(a => a.CouponId == c.Id && a.SkuId == query.SkuId.Value).Any());
            }
            if ( query.QueryKey.IsNotNull() )
            {
                where = where.And(a => a.CouponTitle.Contains(query.QueryKey));
            }
            return where.IsStarted ? (Expression<Func<DBShopCoupon, bool>>)where : null;
        }

        public static Expression<Func<DBShopActivity, bool>> ToWhere ( this ActivityQueryParam query )
        {
            ExpressionStarter<DBShopActivity> where = PredicateBuilder.New<DBShopActivity>();
            if ( query.ActivityType.HasValue )
            {
                where = where.And(c => c.ActivityType == query.ActivityType.Value);
            }
            if ( query.UserRange.HasValue )
            {
                where = where.And(c => c.UserRange == query.UserRange.Value);
            }
            if ( query.Range.HasValue )
            {
                where = where.And(c => c.Range == query.Range.Value);
            }
            if ( !query.Status.IsNull() )
            {
                where = where.And(c => query.Status.Contains(c.ActivityStatus));
            }
            if ( query.Begin.HasValue && query.End.HasValue )
            {
                where = where.And(a => a.BeginTime <= query.End.Value && a.EndTime >= query.Begin.Value);
            }
            else if ( query.Begin.HasValue )
            {
                where = where.And(a => a.BeginTime >= query.Begin.Value);
            }
            else if ( query.End.HasValue )
            {
                where = where.And(a => a.EndTime <= query.End.Value);
            }
            if ( query.SkuId.HasValue )
            {
                where = where.And(c => SqlFunc.Subqueryable<DBShopActivityGoods>().Where(a => a.ActivityId == c.Id && a.SkuId == query.SkuId.Value).Any());
            }
            else if ( query.GoodsId.HasValue )
            {
                where = where.And(c => SqlFunc.Subqueryable<DBShopActivityGoods>().Where(a => a.ActivityId == c.Id && a.GoodsId == query.GoodsId.Value).Any());
            }
            if ( query.QueryKey.IsNotNull() )
            {
                where = where.And(a => a.ActivityTitle.Contains(query.QueryKey));
            }
            return where.IsStarted ? (Expression<Func<DBShopActivity, bool>>)where : null;
        }
        public static Expression<Func<DBAdvert, bool>> ToWhere ( this AdvertQueryParam query )
        {
            ExpressionStarter<DBAdvert> where = PredicateBuilder.New<DBAdvert>(a => a.PlaceId == query.PlaceId);
            if ( query.RelationId.HasValue && query.RelationType.HasValue )
            {
                where = where.And(c => c.RelationType == query.RelationType.Value && c.RelationId == query.RelationId.Value);
            }
            else if ( query.RelationType.HasValue )
            {
                where = where.And(c => c.RelationType == query.RelationType.Value);
            }
            if ( !query.Status.IsNull() )
            {
                where = where.And(c => query.Status.Contains(c.AdvertStatus));
            }
            if ( query.Begin.HasValue && query.End.HasValue )
            {
                long begin = query.Begin.Value.ToLong();
                long end = query.End.Value.ToLong();
                where = where.And(a => a.PutInBegin <= end && a.PutInEnd >= begin);
            }
            else if ( query.Begin.HasValue )
            {
                long begin = query.Begin.Value.ToLong();
                where = where.And(a => a.PutInBegin >= begin);
            }
            else if ( query.End.HasValue )
            {
                long end = query.End.Value.ToLong();
                where = where.And(a => a.PutInEnd <= end);
            }
            if ( query.QueryKey.IsNotNull() )
            {
                where = where.And(a => a.Title.Contains(query.QueryKey));
            }
            return where;
        }
        public static Expression<Func<DBFrontCategory, bool>> ToWhere ( this FrontCategoryGet param )
        {
            ExpressionStarter<DBFrontCategory> where = PredicateBuilder.New<DBFrontCategory>();
            if ( param.IsEnable.HasValue )
            {
                where = where.And(a => a.IsEnable == param.IsEnable.Value);
            }
            if ( param.LevelCode.IsNotNull() )
            {
                where = where.And(a => a.LevelCode.StartsWith(param.LevelCode));
            }
            return where.IsStarted ? (Expression<Func<DBFrontCategory, bool>>)where : null;
        }
        public static Expression<Func<DBCategory, bool>> ToWhere ( this GoodsCategoryGet param )
        {
            ExpressionStarter<DBCategory> where = PredicateBuilder.New<DBCategory>();
            if ( param.IsEnable.HasValue )
            {
                where = where.And(a => a.IsEnable == param.IsEnable.Value);
            }
            if ( param.LevelCode.IsNotNull() )
            {
                where = where.And(a => a.LevelCode.StartsWith(param.LevelCode));
            }
            return where.IsStarted ? (Expression<Func<DBCategory, bool>>)where : null;
        }
        public static Expression<Func<DBLogisticsConfig, bool>> ToWhere ( this LQueryParam query )
        {
            ExpressionStarter<DBLogisticsConfig> where = PredicateBuilder.New<DBLogisticsConfig>(a => a.TemplateId == query.TemplateId);
            if ( !query.QueryKey.IsNull() )
            {
                where = where.And(a => a.AreaName.Contains(query.QueryKey));
            }
            if ( query.IsEnable.HasValue )
            {
                where = where.And(a => a.IsEnable == query.IsEnable.Value);
            }
            return where;
        }
        public static Expression<Func<DBGoods, bool>> ToWhere ( this GoodsQuery query )
        {
            ExpressionStarter<DBGoods> where = PredicateBuilder.New<DBGoods>();
            if ( !query.QueryKey.IsNull() )
            {
                where = query.QueryKey.Validate(ValidateFormat.数字字母)
                    ? (ExpressionStarter<DBGoods>)where.And(a => a.GoodsSpu.StartsWith(query.QueryKey))
                    : (ExpressionStarter<DBGoods>)where.And(a => a.GoodsName.Contains(query.QueryKey));
            }
            if ( query.CategoryId.HasValue && query.Lvl.HasValue )
            {
                switch ( query.Lvl.Value )
                {
                    case 1:
                        where = where.And(a => a.MainCategoryId == query.CategoryId.Value);
                        break;
                    case 2:
                        where = where.And(a => a.TwoCategoryId == query.CategoryId.Value);
                        break;
                    case 3:
                        where = where.And(a => a.ThreeCategoryId == query.CategoryId.Value);
                        break;
                    default:
                        where = where.And(a => a.CategoryId == query.CategoryId.Value);
                        break;
                }
            }
            if ( query.Stock.HasValue )
            {
                where = where.And(a => SqlFunc.Subqueryable<DBGoodsStock>().Where(b => b.GoodsId == a.Id && SqlFunc.Between(b.CurStock, 0, query.Stock.Value)).Any());
            }
            if ( !query.Status.IsNull() )
            {
                where = query.Status.Length == 1 ? (ExpressionStarter<DBGoods>)where.And(a => a.Status == query.Status[0]) : (ExpressionStarter<DBGoods>)where.And(a => query.Status.Contains(a.Status));
            }
            return where.And(a => a.IsDrop == false);
        }
        public static Expression<Func<DBLogisticsTemplate, bool>> ToWhere ( this LTQueryParam query )
        {
            return query.QueryKey.IsNull() ? null : (Expression<Func<DBLogisticsTemplate, bool>>)PredicateBuilder.New<DBLogisticsTemplate>(a => a.TemplateName.Contains(query.QueryKey));
        }

    }
}
